//! 路由表

use crate::consts::*;
use crate::id::*;
use crate::link::{ErrorKind, Link};
use heapless::LinearMap;
use heapless::Vec;
use log::*;
use spin::Lazy;
use spin::RwLock;

static PARENT: Lazy<RwLock<Vec<Link, ParentLen>>> = Lazy::new(|| RwLock::new(Vec::new()));
static CHILDREN: Lazy<RwLock<LinearMap<Id, Link, ChildLen>>> =
    Lazy::new(|| RwLock::new(LinearMap::new()));

/// 更新路由到路由表上
pub fn add(id: &Id, link: Link) -> bool {
    if PARENT.read().contains(&link) {
        return true;
    }
    if id.kind() == IdKind::Test {
        if id != &ID_PARENT {
            return false;
        }
        let mut parents = PARENT.write();
        if let Err(link) = parents.push(link) {
            for i in 0..parents.len() {
                if i >= parents.len() {
                    break;
                }
                while !parents[i].has() {
                    parents.swap_remove(i);
                    if i >= parents.len() {
                        break;
                    }
                }
            }
            if let Err(_) = parents.push(link) {
                panic!("unmp route parent too much.");
            }
        };
        return true;
    }

    if let Some(route) = CHILDREN.write().get_mut(id) {
        *route = link;
        return true;
    }
    let _err = CHILDREN.write().insert(id.clone(), link);
    return true;
}
/// 打印路由信息
#[allow(dead_code)]
pub fn info() {
    info!("print unmp route.");
    info!("parent: {:?}", PARENT.read());
    for (id, route) in CHILDREN.read().iter() {
        info!("id {:?}: {:?}", id, route);
    }
}
/// 获取链路
pub fn get_link(id: &Id) -> Option<Link> {
    if id.kind() == IdKind::Test {
        return None;
    }
    if let Some(link) = CHILDREN.write().get(id) {
        return Some(*link);
    } else {
        return None;
    }
}
/// 发送数据给目标地址
pub fn sendto(id: &Id, buf: &[u8], origin: Option<Link>) -> Result<(), ()> {
    let mut success = 0;
    if id.kind() == IdKind::Test {
        if id != &ID_PARENT {
            return Err(());
        }
        let mut rm_queue: Vec<usize, ParentLen> = Vec::new();
        let mut parent = PARENT.write();
        for i in 0..parent.len() {
            if origin == Some(parent[i]) {
                continue;
            }
            match parent[i].send(buf) {
                Ok(_) => {
                    success += 1;
                }
                Err(ErrorKind::NotFound) => {
                    rm_queue.push(i).unwrap();
                }
                Err(_) => {}
            }
        }
        while let Some(i) = rm_queue.pop() {
            parent.swap_remove(i);
        }
        return if success == 0 { Err(()) } else { Ok(()) };
    }

    let mut children = CHILDREN.write();
    let route = {
        if let Some(route) = children.get_mut(id) {
            route
        } else {
            return Err(());
        }
    };
    if origin == Some(*route) {
        return Err(());
    }
    match route.send(buf) {
        Ok(_) => {
            success += 1;
        }
        Err(ErrorKind::NotFound) => {
            drop(route);
            children.remove(id);
        }
        Err(_) => {}
    }
    return if success == 0 { Err(()) } else { Ok(()) };
}
